"""
聊天路由模块
处理实时聊天功能
"""
from flask import Blueprint, render_template, redirect, url_for, flash, request, jsonify
from flask_login import login_required, current_user
from flask_socketio import emit, join_room, leave_room

from app import db, socketio
from app.models.chat import ChatRoom, Message, UserChatRoom
from app.models.user import User
from app.auth.decorators import handle_exceptions, permission_required
from app.utils.helpers import format_timestamp

chat_bp = Blueprint('chat', __name__, url_prefix='/chat')

# Socket.IO 事件处理
@socketio.on('connect')
def handle_connect():
    """
    处理客户端连接
    """
    if current_user.is_authenticated:
        # 更新用户在线状态
        current_user.update_online_status(True)
        db.session.commit()
        
        # 加入用户的个人房间
        join_room(f'user_{current_user.id}')
        
        # 通知其他用户该用户上线
        emit('user_online', {
            'user_id': current_user.id,
            'username': current_user.username
        }, broadcast=True, include_self=False)
        
        print(f"用户 {current_user.username} 已连接")

@socketio.on('disconnect')
def handle_disconnect():
    """
    处理客户端断开连接
    """
    if current_user.is_authenticated:
        # 更新用户在线状态
        current_user.update_online_status(False)
        db.session.commit()
        
        # 通知其他用户该用户下线
        emit('user_offline', {
            'user_id': current_user.id,
            'username': current_user.username
        }, broadcast=True, include_self=False)
        
        print(f"用户 {current_user.username} 已断开连接")

@socketio.on('join_room')
def handle_join_room(data):
    """
    加入聊天室
    """
    if not current_user.is_authenticated:
        return
    
    room_id = data.get('room_id')
    if room_id:
        join_room(f'room_{room_id}')
        
        # 通知房间内其他用户
        emit('user_joined', {
            'user_id': current_user.id,
            'username': current_user.username,
            'room_id': room_id
        }, room=f'room_{room_id}', include_self=False)
        
        print(f"用户 {current_user.username} 加入了房间 {room_id}")

@socketio.on('leave_room')
def handle_leave_room(data):
    """
    离开聊天室
    """
    if not current_user.is_authenticated:
        return
    
    room_id = data.get('room_id')
    if room_id:
        leave_room(f'room_{room_id}')
        
        # 通知房间内其他用户
        emit('user_left', {
            'user_id': current_user.id,
            'username': current_user.username,
            'room_id': room_id
        }, room=f'room_{room_id}', include_self=False)
        
        print(f"用户 {current_user.username} 离开了房间 {room_id}")

@socketio.on('send_message')
def handle_send_message(data):
    """
    发送聊天消息
    """
    if not current_user.is_authenticated:
        return
    
    room_id = data.get('room_id')
    content = data.get('content', '').strip()
    
    if not room_id or not content:
        return
    
    if len(content) > 1000:
        emit('error', {'message': '消息内容过长'})
        return
    
    try:
        # 检查用户是否在房间中
        user_room = UserChatRoom.query.filter_by(
            user_id=current_user.id,
            room_id=room_id
        ).first()
        
        if not user_room:
            emit('error', {'message': '您不在这个聊天室中'})
            return
        
        # 创建消息
        message = Message(
            content=content,
            author_id=current_user.id,
            room_id=room_id
        )
        
        db.session.add(message)
        db.session.commit()
        
        # 构建消息数据
        message_data = {
            'id': message.id,
            'content': message.content,
            'author': {
                'id': current_user.id,
                'username': current_user.username,
                'avatar_url': current_user.avatar_url
            },
            'room_id': room_id,
            'created_at': format_timestamp(message.created_at),
            'is_own': True
        }
        
        # 发送消息到房间
        emit('new_message', message_data, room=f'room_{room_id}')
        
        print(f"用户 {current_user.username} 在房间 {room_id} 发送了消息")
    
    except Exception as e:
        db.session.rollback()
        emit('error', {'message': '发送消息失败'})
        print(f"发送消息失败: {str(e)}")

# HTTP 路由
@chat_bp.route('/')
@login_required
def index():
    """
    聊天主页 - 显示聊天室列表
    """
    # 获取用户加入的聊天室
    user_rooms = ChatRoom.query.join(UserChatRoom)\
        .filter(UserChatRoom.user_id == current_user.id)\
        .filter(ChatRoom.is_active == True)\
        .order_by(ChatRoom.created_at.desc())\
        .all()
    
    # 获取公共聊天室
    public_rooms = ChatRoom.query.filter_by(
        is_public=True,
        is_active=True
    ).order_by(ChatRoom.member_count.desc())\
     .limit(10)\
     .all()
    
    # 获取在线用户
    online_users = User.query.filter_by(is_online=True)\
        .order_by(User.last_seen.desc())\
        .limit(20)\
        .all()
    
    return render_template('chat/index.html',
                         user_rooms=user_rooms,
                         public_rooms=public_rooms,
                         online_users=online_users)

@chat_bp.route('/room/<int:room_id>')
@login_required
def view_room(room_id):
    """
    查看聊天室
    """
    room = ChatRoom.query.get_or_404(room_id)
    
    # 检查用户是否有权限访问
    if not room.is_public:
        user_in_room = UserChatRoom.query.filter_by(
            user_id=current_user.id,
            room_id=room_id
        ).first()
        
        if not user_in_room and not current_user.is_admin:
            flash('您无权访问此聊天室', 'danger')
            return redirect(url_for('chat.index'))
    
    # 获取聊天室成员
    members = User.query.join(UserChatRoom)\
        .filter(UserChatRoom.room_id == room_id)\
        .order_by(UserChatRoom.joined_at.desc())\
        .all()
    
    # 获取消息历史
    messages = Message.query.filter_by(room_id=room_id)\
        .order_by(Message.created_at.asc())\
        .limit(100)\
        .all()
    
    return render_template('chat/room.html',
                         room=room,
                         members=members,
                         messages=messages)

@chat_bp.route('/create-room', methods=['GET', 'POST'])
@login_required
@handle_exceptions
def create_room():
    """
    创建聊天室
    """
    if request.method == 'GET':
        return render_template('chat/create_room.html')
    
    # POST请求处理聊天室创建
    try:
        name = request.form.get('name', '').strip()
        description = request.form.get('description', '').strip()
        is_public = bool(request.form.get('is_public'))
        max_members = request.form.get('max_members', type=int) or 50
        
        # 验证输入
        if not name:
            flash('请填写聊天室名称', 'danger')
            return redirect(url_for('chat.create_room'))
        
        if len(name) > 50:
            flash('聊天室名称不能超过50个字符', 'danger')
            return redirect(url_for('chat.create_room'))
        
        if len(description) > 200:
            flash('聊天室描述不能超过200个字符', 'danger')
            return redirect(url_for('chat.create_room'))
        
        # 创建聊天室
        room = ChatRoom(
            name=name,
            description=description,
            is_public=is_public,
            max_members=max_members,
            created_by=current_user.id
        )
        
        db.session.add(room)
        db.session.flush()  # 获取room.id
        
        # 将创建者加入聊天室
        user_room = UserChatRoom(
            user_id=current_user.id,
            room_id=room.id,
            role='admin'  # 创建者是管理员
        )
        
        db.session.add(user_room)
        
        # 更新成员计数
        room.member_count += 1
        
        db.session.commit()
        
        flash('聊天室创建成功！', 'success')
        return redirect(url_for('chat.view_room', room_id=room.id))
    
    except Exception as e:
        db.session.rollback()
        flash('聊天室创建失败，请稍后重试', 'danger')
        return redirect(url_for('chat.create_room'))

@chat_bp.route('/room/<int:room_id>/join', methods=['POST'])
@login_required
@handle_exceptions
def join_room(room_id):
    """
    加入聊天室
    """
    room = ChatRoom.query.get_or_404(room_id)
    
    # 检查聊天室状态
    if not room.is_active:
        return jsonify({
            'success': False,
            'message': '聊天室已关闭'
        }), 400
    
    # 检查是否已满
    if room.member_count >= room.max_members:
        return jsonify({
            'success': False,
            'message': '聊天室已满'
        }), 400
    
    # 检查是否已加入
    existing_join = UserChatRoom.query.filter_by(
        user_id=current_user.id,
        room_id=room_id
    ).first()
    
    if existing_join:
        return jsonify({
            'success': False,
            'message': '您已经在这个聊天室中了'
        }), 400
    
    try:
        # 加入聊天室
        user_room = UserChatRoom(
            user_id=current_user.id,
            room_id=room_id,
            role='member'
        )
        
        db.session.add(user_room)
        
        # 更新成员计数
        room.member_count += 1
        
        db.session.commit()
        
        return jsonify({
            'success': True,
            'message': '已成功加入聊天室',
            'redirect_url': url_for('chat.view_room', room_id=room_id)
        })
    
    except Exception as e:
        db.session.rollback()
        return jsonify({
            'success': False,
            'message': '加入聊天室失败'
        }), 500

@chat_bp.route('/room/<int:room_id>/leave', methods=['POST'])
@login_required
@handle_exceptions
def leave_room(room_id):
    """
    离开聊天室
    """
    user_room = UserChatRoom.query.filter_by(
        user_id=current_user.id,
        room_id=room_id
    ).first_or_404()
    
    room = user_room.room
    
    try:
        # 如果是创建者离开，需要转移所有权或关闭房间
        if room.created_by == current_user.id:
            # 查找其他管理员
            other_admin = UserChatRoom.query.filter(
                UserChatRoom.room_id == room_id,
                UserChatRoom.user_id != current_user.id,
                UserChatRoom.role == 'admin'
            ).first()
            
            if other_admin:
                # 转移创建者权限
                room.created_by = other_admin.user_id
            else:
                # 没有其他管理员，关闭房间
                room.is_active = False
        
        # 移除用户
        db.session.delete(user_room)
        
        # 更新成员计数
        if room.member_count > 0:
            room.member_count -= 1
        
        db.session.commit()
        
        return jsonify({
            'success': True,
            'message': '已成功离开聊天室',
            'redirect_url': url_for('chat.index')
        })
    
    except Exception as e:
        db.session.rollback()
        return jsonify({
            'success': False,
            'message': '离开聊天室失败'
        }), 500

@chat_bp.route('/private/<int:user_id>')
@login_required
@handle_exceptions
def private_chat(user_id):
    """
    私聊页面
    """
    target_user = User.query.get_or_404(user_id)
    
    if target_user.id == current_user.id:
        flash('不能与自己私聊', 'warning')
        return redirect(url_for('chat.index'))
    
    # 查找或创建私聊房间
    # 私聊房间的name格式: private_{user1_id}_{user2_id}，按ID排序
    user1_id, user2_id = sorted([current_user.id, target_user.id])
    room_name = f'private_{user1_id}_{user2_id}'
    
    room = ChatRoom.query.filter_by(name=room_name, is_public=False).first()
    
    if not room:
        # 创建私聊房间
        room = ChatRoom(
            name=room_name,
            description=f'{current_user.username} 和 {target_user.username} 的私聊',
            is_public=False,
            is_private=True,
            max_members=2,
            created_by=current_user.id
        )
        
        db.session.add(room)
        db.session.flush()
        
        # 添加两个用户到房间
        user1_room = UserChatRoom(user_id=user1_id, room_id=room.id, role='member')
        user2_room = UserChatRoom(user_id=user2_id, room_id=room.id, role='member')
        
        db.session.add_all([user1_room, user2_room])
        room.member_count = 2
        
        db.session.commit()
    
    return redirect(url_for('chat.view_room', room_id=room.id))

# API 路由
@chat_bp.route('/api/rooms')
@login_required
def api_rooms():
    """
    API: 获取聊天室列表
    """
    page = request.args.get('page', 1, type=int)
    per_page = request.args.get('per_page', 20, type=int)
    
    rooms_query = ChatRoom.query.filter_by(is_active=True, is_public=True)
    
    rooms = rooms_query.order_by(ChatRoom.member_count.desc())\
        .paginate(page=page, per_page=per_page, error_out=False)
    
    rooms_data = []
    for room in rooms.items:
        rooms_data.append({
            'id': room.id,
            'name': room.name,
            'description': room.description,
            'member_count': room.member_count,
            'max_members': room.max_members,
            'is_public': room.is_public,
            'created_at': format_timestamp(room.created_at)
        })
    
    return jsonify({
        'success': True,
        'rooms': rooms_data,
        'pagination': {
            'page': rooms.page,
            'per_page': rooms.per_page,
            'total': rooms.total,
            'pages': rooms.pages
        }
    })

@chat_bp.route('/api/rooms/<int:room_id>/messages')
@login_required
def api_room_messages(room_id):
    """
    API: 获取聊天室消息
    """
    # 检查用户是否在房间中
    user_room = UserChatRoom.query.filter_by(
        user_id=current_user.id,
        room_id=room_id
    ).first()
    
    if not user_room and not current_user.is_admin:
        return jsonify({
            'success': False,
            'message': '无权访问此聊天室'
        }), 403
    
    page = request.args.get('page', 1, type=int)
    per_page = request.args.get('per_page', 50, type=int)
    
    messages_query = Message.query.filter_by(room_id=room_id)
    
    messages = messages_query.order_by(Message.created_at.desc())\
        .paginate(page=page, per_page=per_page, error_out=False)
    
    messages_data = []
    for message in messages.items:
        messages_data.append({
            'id': message.id,
            'content': message.content,
            'author': {
                'id': message.author.id,
                'username': message.author.username,
                'avatar_url': message.author.avatar_url
            },
            'created_at': format_timestamp(message.created_at),
            'is_own': message.author_id == current_user.id
        })
    
    # 反转消息顺序（最新的在前面）
    messages_data.reverse()
    
    return jsonify({
        'success': True,
        'messages': messages_data,
        'pagination': {
            'page': messages.page,
            'per_page': messages.per_page,
            'total': messages.total,
            'pages': messages.pages
        }
    })